package com.taichuan.selfcheck.ui.fragment;

import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.TextureView;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Switch;
import android.widget.TextView;
import com.orhanobut.logger.Logger;
import com.taichuan.camera.CameraIdTypeUtils;
import com.taichuan.camera.TcCameraManager;
import com.taichuan.camera.TcCameraVariable;
import com.taichuan.camera.TcTextureViewCameraUtils;
import com.taichuan.camera.VankeSiteBoxCameraIdTypeUtils;
import com.taichuan.keysupport.Key;
import com.taichuan.keysupport.view.KSSpinner;
import com.taichuan.selfcheck.R;
import com.taichuan.selfcheck.SelfCheckAppModuleConfig;
import com.taichuan.selfcheck.config.PathConfig;
import com.taichuan.selfcheck.config.PropertyDefaultValue;
import com.taichuan.selfcheck.hardware.LightControlUtils;
import com.taichuan.selfcheck.mvp.presenter.TestCameraPresenter;
import com.taichuan.selfcheck.mvp.viewinterface.TestCameraInterface;
import com.taichuan.selfcheck.ui.dialog.ResultDialog;
import com.taichuan.selfcheck.ui.fragment.base.AppBaseFragment;
import com.taichuan.tcutils.taichuan.SystemUtils;
import com.taichuan.tcutils.taichuan.TcDeviceType;
import butterknife.BindView;
import butterknife.OnClick;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;

/**
 * 该类主要用于
 *
 * @author CamelLuo
 * @version 2019/12/4
 */
public class TestCameraFragment extends AppBaseFragment<TestCameraInterface, TestCameraPresenter> implements TestCameraInterface {
    private static final String TAG = TestCameraFragment.class.getSimpleName();

    public static final int CAMERA_TYPE_COLOR = 0;         //彩色摄像头
    public static final int CAMERA_TYPE_INFRARED = 1;     //红外摄像头
    public static final int CAMERA_TYPE_TAKE_PHOTO = 2;     //万科智慧工地项目-拍单摄像头

    public static final String PARMA_CAMERA_TYPE = "PARMA_CAMERA_TYPE";

    private static final int REFRESH_CAMERA_INIT_INFO = 1;              //更新相机初始化耗时信息
    private static final int REFRESH_CAMERA_PARMA_INFO = 2;             //更新相机参数信息
    private static final int REFRESH_CAMERA_CALLBACK_DATA_INFO = 3;     //更新相机数据回调信息
    private static final int START_AUTO_TAKE_PHOTO = 4;                 //开始执行自动抓拍
    private static final int REFRESH_TAKE_PHOTO_IMAGE = 5;              //刷新自动抓拍获取到的视频帧数据到ImageView中
    private static final int STOP_AUTO_TAKE_PHOTO = 6;                  //停止执行自动抓拍
    private static final int MSG_CAMERA_ERROR = 7;                      //摄像头出现异常

    /**
     * 摄像头出现异常的 超时判定时间为 2秒
     */
    private static final int CAMERA_ERROR_TIMEOUT_TIME = 2 * 1000;

    /**
     * 执行自动抓拍的抓拍间隔时间
     */
    private static final int AUTO_TAKE_PHOTO_DELAY_TIME = 5 * 1000;

//    /**
//     * 记录执行连续抓拍的次数
//     */
//    private int take_photo_number = 0;

//    /**
//     * 连续抓拍的间隔时间
//     */
//    private static final int CONTINUOUS_TAKE_PHOTO_DELAY_TIME = 1*1000;

    @BindView(R.id.activity_test_camera_button_layout)
    LinearLayout activityTestCameraButtonLayout;
    @BindView(R.id.activity_test_camera_button2_layout)
    LinearLayout activityTestCameraButton2Layout;
    @BindView(R.id.fragment_test_camera_takephoto_imageView)
    ImageView takephotoIv;
    @BindView(R.id.activity_test_camera_delay_time_textView)
    TextView delayTimeTv;
    @BindView(R.id.activity_test_camera_control_fill_light_button)
    Button controlFillLightBtn;
    @BindView(R.id.activity_test_camera_control_infrard_light_button)
    Button controlInfrardLightBtn;
    @BindView(R.id.activity_test_camera_take_photo_button)
    Button takePhotoBtn;
    @BindView(R.id.activity_test_camera_browse_photo_button)
    Button browsePhotoBtn;

    /**
     * 定义一组变量用于控制预览画面的分辨率宽高，如不知道可都先填0，程序会自动使用默认的分辨率配置
     */
    private int PREVIEW_IMAGE_WIDTH = 640;
    private int PREVIEW_IMAGE_HEIGHT = 360;

    @BindView(R.id.activity_test_camera_start_preview_button)
    Button startPreviewButton;
    @BindView(R.id.activity_test_camera_stop_preview_button)
    Button stopPreviewButton;
    @BindView(R.id.face_recog_content_layout)
    RelativeLayout contentLayout;
    @BindView(R.id.camera_data_callback_switch)
    Switch dataCallbackCb;
    @BindView(R.id.activity_test_camera_init_info_textView)
    TextView cameraInitInfoTv;
    @BindView(R.id.activity_test_camera_parma_textView)
    TextView cameraParmaTv;
    @BindView(R.id.fragment_test_camera_preview_size_type_spinner)
    KSSpinner previewSizeTypeSp;
    @BindView(R.id.fragment_test_camera_auto_takephoto_switch)
    Switch autoTakephotoSwitch;

    private TcTextureViewCameraUtils cameraUtils;

    private TextureView cameraPreviewView;

    private ColorCameraPreviewCallback colorCameraPreviewCallback;

    /**
     * 定义一个变量用于记录摄像头开始调用 初始化函数前的时间
     */
    private long cameraInitStartTime;
    /**
     * 定义一个变量用于记录 摄像头调用 初始化函数 的执行时间
     */
    private long cameraInitTime;
    /**
     * 定义一个变量用于记录 摄像头 【初始化结束】后 到 接收到第一帧数据回调 的执行时间
     */
    private long cameraGetDataTime;
    /**
     * 定义一个变量用于记录 摄像头 初始化开始 到 接收到第一帧数据回调 的执行时间
     */
    private long cameraInitTotalTime;
    /**
     * 定义一个变量用于记录 摄像头 上一帧数据回调 的获取时间
     */
    private long lastCameraPreviewDataTime;

    /**
     * 定义一个变量用于控制 是否需要数据回调，默认开启
     */
    private boolean isNeedDataCallback = true;

    /**
     * 定义一个变量用于控制 是否开启自动抓拍功能,默认不开启
     */
    private boolean isAutoTakePhoto = false;

    /**
     * 定义一个变量用于记录是否为 第一次接收到相机数据回调
     */
    private boolean isFristDataCallback = true;
    /**
     * 定义一个变量用于记录当前选择的摄像头类型
     */
    private int cameraType;

    /**
     * 定义一个变量用于控制 是否处于重置状态
     */
    private boolean isInResetUsbCamera = false;

    /**
     * 定义一个变量用于记录页面是否第一次触发了Spinner控件的 选择事件回调监听
     * 由于Android Spinner 的奇怪特性，在设置了Spinner控件的选择监听回调事件后，页面初始化Spinner时会自动执行选择第一项item
     * 的操作，导致触发了选择事件回调监听（OnItemSelectedListener），从而误执行了回调监听中的业务逻辑，因此用该变量限制
     */
    private boolean isFristSelectSpinner = true;

    private String[] previewSizeValueArray;

    ResultDialog resultDialog;

    @Override
    protected void getBundleValues(Bundle bundle) {
        if (bundle != null) {
            cameraType = bundle.getInt(PARMA_CAMERA_TYPE, CAMERA_TYPE_COLOR);
            Log.e(TAG, "initBundle: 当前启动的摄像头类型为：  " + cameraType);
        }

    }

    public static Bundle setBundleValue(int cameraType) {
        Bundle bundle = new Bundle();
        bundle.putInt(PARMA_CAMERA_TYPE, cameraType);
        return bundle;
    }

    @Override
    protected int setContentViewId() {
        if (SystemUtils.getTcDeviceType() == TcDeviceType.A33_LANDSCAPE_KEY ||
                SystemUtils.getTcDeviceType() == TcDeviceType.A64_LANDSCAPE_KEY ||
                SystemUtils.getTcDeviceType() == TcDeviceType.L10_Pro ||
                SystemUtils.getTcDeviceType() == TcDeviceType.RK3399_LANDSCAPE_KEY ||
                SystemUtils.getTcDeviceType() == TcDeviceType.A33_LANDSCAPE_KEY_L1) {          //横屏 设备
            return R.layout.fragment_camera_test_a33_land;
        } else {                                                                         //其他设备
            return R.layout.fragment_camera_test_normal;
        }
    }

    @Override
    protected void initView(View view, Bundle bundle) {
        isFristDataCallback = true;
        //初始化Button
        initButton();
        //初始化Switch开关
        initSwitch();
        //初始化Spinner
        initSpinner();
        //初始化摄像头预览控件
        initPreviewView();
        //初始化摄像头工具类
        initCamera();
        //初始化测试结果Dialog
        resultDialog = new ResultDialog(PropertyDefaultValue.FUNCTION_TEST_4, getResources().getString(R.string.camera), getContext());       //设置弹窗发送的事件——摄像头测试
        //按键版Spinner
        initViewFoucs();
    }

    private void initButton() {
        controlFillLightBtn.setTag("open");
        //支持红外灯的设备才显示该按钮
        controlInfrardLightBtn.setTag("open");
        if (SystemUtils.isRk3399() && (cameraType == CAMERA_TYPE_INFRARED)){
                controlInfrardLightBtn.setVisibility(View.VISIBLE);
            controlFillLightBtn.setTag("close");
            controlFillLightBtn.setText(getStrById(R.string.btn_camera_test_open_fill_light));
        }else{
            controlInfrardLightBtn.setVisibility(View.INVISIBLE);
        }
    }

    private void initViewFoucs() {
        mViewFocus.add(cameraInitInfoTv);
        mViewFocus.add(previewSizeTypeSp);
        mViewFocus.requestFocus(previewSizeTypeSp);
    }

    /**
     * 定义一个方法用于初始化Switch控件
     */
    private void initSwitch() {
        dataCallbackCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                isNeedDataCallback = isChecked;
                if (isNeedDataCallback) {
                    cameraUtils.setPreviewCallback(colorCameraPreviewCallback);
                } else {
                    cameraUtils.setPreviewCallback(null);
                }
            }
        });
        autoTakephotoSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                isAutoTakePhoto = isChecked;
                if (isAutoTakePhoto) {
                    //启动自动抓拍流程
                    handler.sendEmptyMessageDelayed(START_AUTO_TAKE_PHOTO, AUTO_TAKE_PHOTO_DELAY_TIME);
                } else {
                    //停止自动抓拍流程
                    handler.sendEmptyMessage(STOP_AUTO_TAKE_PHOTO);
                }
            }
        });
    }

    /**
     * 定义一个方法用于初始化Spinner控件
     */
    private void initSpinner() {
        //获取下拉列表显示内容的结果值数组
        previewSizeValueArray = mActivity.getResources().getStringArray(R.array.camera_preview_size_type_value);

        //A64 和 Rk3399设备 默认使用1280*720 分辨率
        if (SystemUtils.isRk3399() || SystemUtils.isA64()) {               //RK3399 设备 和 A64设备
            if (cameraType == CAMERA_TYPE_TAKE_PHOTO){                     //万科智慧工地项目 设备 的拍单摄像头
                //拍单摄像头默认使用2k分辨率进行预览
                previewSizeTypeSp.setSelection(4);
                PREVIEW_IMAGE_WIDTH = 2560;
                PREVIEW_IMAGE_HEIGHT = 1440;
            }else {
                previewSizeTypeSp.setSelection(2);
                PREVIEW_IMAGE_WIDTH = 1280;
                PREVIEW_IMAGE_HEIGHT = 720;
            }
        }

        previewSizeTypeSp.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                if (!isFristSelectSpinner) {
                    if (previewSizeValueArray != null && previewSizeValueArray.length > 0 && position <= previewSizeValueArray.length) {
                        //rk3399机型需限制可使用的预览分辨率
                        if (SystemUtils.isRk3399()) {
                            if (position == 0) {
                                showMsg("该设备不支持使用640*360分辨率进行摄像头预览");
                                return;
                            } else if (position == 3) {
                                if (cameraType == CAMERA_TYPE_INFRARED) {
                                    showMsg("该设备红外摄像头不支持使用1920*1080分辨率进行摄像头预览");
                                    return;
                                }
                            }else if (position == 4){
                                if (cameraType != CAMERA_TYPE_TAKE_PHOTO){
                                    showMsg("该设备不支持使用2560*1440分辨率进行摄像头预览");
                                    return;
                                }
                            }
                        }

                        //获取选中的分辨率
                        String previewSize = previewSizeValueArray[position];
                        //根据分隔符获取分辨率的宽度和高度
                        String[] previewSizeSplit = previewSize.split("@");
                        if (previewSizeSplit.length == 2) {
                            PREVIEW_IMAGE_WIDTH = Integer.parseInt(previewSizeSplit[0]);
                            PREVIEW_IMAGE_HEIGHT = Integer.parseInt(previewSizeSplit[1]);
                            //设置预览分辨率
                            cameraUtils.setPreviewViewSize(PREVIEW_IMAGE_WIDTH, PREVIEW_IMAGE_HEIGHT);

                            showMsg("选择了" + PREVIEW_IMAGE_WIDTH + " * " + PREVIEW_IMAGE_HEIGHT + " 作为预览分辨率");

                            //如果页面已经在进行画面预览了则直接切换分辨率
                            Logger.t(TAG).e("当前视频控件的预览状态为：  " + cameraUtils.getCameraUtilPreviewState());
                            if (cameraUtils.getCameraUtilPreviewState() == TcTextureViewCameraUtils.CAMERA_UTIL_PREVIEW_STATE_IN_PREVIEW) {
                                //变更视频预览分辨率
                                reStartPreview();
                            }
                        } else {
                            showMsg("切换分辨率异常，请重试");
                        }
                    } else {
                        showMsg("切换分辨率异常，请重试");
                    }
                } else {
                    isFristSelectSpinner = false;
                    Log.i(TAG, "onItemSelected: 首次触发，不执行业务流程");
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });
    }

    /**
     * 定义一个方法用于初始化摄像头预览画面控件
     */
    private void initPreviewView() {
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
        //创建视频预览显示控件
        cameraPreviewView = new TextureView(getActivity());
        //设置TextureView状态监听
        cameraPreviewView.setSurfaceTextureListener(new CameraTextureListener());
        //将预览控件添加到布局中
        contentLayout.addView(cameraPreviewView, params);
    }

    /**
     * 定义一个方法用于初始化摄像头工具类
     */
    private void initCamera() {
        //刷新获取摄像头下标，防止设备因极端情况下（静电，摄像头异常，手动开关USB摄像头操作） 导致摄像头下标混乱
//        CameraIdTypeUtils.getInstance().checkCheShenCameraIdType();
        //实例化相机工具类
        cameraUtils = new TcTextureViewCameraUtils(getActivity(), cameraPreviewView.getSurfaceTexture(),
                SelfCheckAppModuleConfig.getCameraPreviewOration(),TAG);
        //Rk3399 设备下才有双摄摄像头
        if (SystemUtils.isRk3399()) {
            if (!SystemUtils.isVankeSiteBoxDevice()){       //普通RK3399 设备
                if (cameraType == CAMERA_TYPE_COLOR) {
                    int colorCameraId = CameraIdTypeUtils.getInstance().getColorCameraId();
                    Log.e(TAG, "initCamera: 获取到的彩色摄像头下标为：  " + colorCameraId);
                    cameraUtils.setOpenCameraId(colorCameraId, TcCameraVariable.CameraIdType.CAMERA_ID_TYPE_COLOR, TcCameraVariable.CameraDeviceMode.CAMERA_DEVICE_MODE_DOUBLE);
                    //开启补光灯
                    LightControlUtils.getInstance().controlFillLight(true, false);
                } else if (cameraType == CAMERA_TYPE_INFRARED) {
                    int infraredCameraId = CameraIdTypeUtils.getInstance().getInfraredCameraId();
                    Log.e(TAG, "initCamera: 获取到的黑白摄像头下标为：  " + infraredCameraId);
                    if (SystemUtils.getTcDeviceType() == TcDeviceType.RK3399_VERTICAL_TOUCH_O8A_DOOR){
                        cameraUtils.setOpenCameraId(infraredCameraId, TcCameraVariable.CameraIdType.CAMERA_ID_TYPE_INFRARD,
                                TcCameraVariable.CameraDeviceMode.CAMERA_DEVICE_MODE_DOUBLE_WITH_AUTO_INFRARD_LIGHT);
                        Log.e(TAG, "initCamera: 当前打开的为 TC-Y9D-O8A 设备的红外摄像头");
                    }else {
                        cameraUtils.setOpenCameraId(infraredCameraId, TcCameraVariable.CameraIdType.CAMERA_ID_TYPE_INFRARD,
                                TcCameraVariable.CameraDeviceMode.CAMERA_DEVICE_MODE_DOUBLE);
                        //开启红外灯
                        LightControlUtils.getInstance().openOrCloseInfraredLight(true);
                    }
                }
            }else {                 //万科智慧工地项目-设备
                if (cameraType == CAMERA_TYPE_COLOR) {
                    int colorCameraId = VankeSiteBoxCameraIdTypeUtils.getInstance().getColorCameraId();
                    Log.e(TAG, "initCamera: 获取到【万科智慧工地项目设备】的彩色摄像头下标为：  " + colorCameraId);
                    cameraUtils.setOpenCameraId(colorCameraId, TcCameraVariable.CameraIdType.CAMERA_ID_TYPE_COLOR,
                            TcCameraVariable.CameraDeviceMode.CAMERA_DEVICE_MODE_MULTI);
                    //开启补光灯
                    LightControlUtils.getInstance().controlFillLight(true, false);
                } else if (cameraType == CAMERA_TYPE_INFRARED) {
                    int infraredCameraId = VankeSiteBoxCameraIdTypeUtils.getInstance().getInfraredCameraId();
                    Log.e(TAG, "initCamera: 获取到【万科智慧工地项目设备】的黑白摄像头下标为：  " + infraredCameraId);
                    cameraUtils.setOpenCameraId(infraredCameraId, TcCameraVariable.CameraIdType.CAMERA_ID_TYPE_INFRARD,
                            TcCameraVariable.CameraDeviceMode.CAMERA_DEVICE_MODE_MULTI);
                    //开启红外灯
                    LightControlUtils.getInstance().openOrCloseInfraredLight(true);
                }else if (cameraType == CAMERA_TYPE_TAKE_PHOTO){
                    int takePhotoCameraId = VankeSiteBoxCameraIdTypeUtils.getInstance().getTakePhotoCameraId();
                    Log.e(TAG, "initCamera: 获取到【万科智慧工地项目设备】的拍单摄像头下标为：  " + takePhotoCameraId);
                    cameraUtils.setOpenCameraId(takePhotoCameraId, TcCameraVariable.CameraIdType.CAMERA_ID_TYPE_TAKE_PHOTO,
                            TcCameraVariable.CameraDeviceMode.CAMERA_DEVICE_MODE_MULTI);
                    //万科智慧工地主板使用 曝光补偿值 来开启补光灯
                    cameraUtils.setCameraExposureCompensation(1);
                }
            }
        } else {     //单摄像头设备，打开下标为0的摄像头
            cameraUtils.setOpenCameraId(0, TcCameraVariable.CameraIdType.CAMERA_ID_TYPE_COLOR, TcCameraVariable.CameraDeviceMode.CAMERA_DEVICE_MODE_NORMAL);
            //开启补光灯
            LightControlUtils.getInstance().controlFillLight(true, false);
        }

        //设置预览分辨率
        cameraUtils.setPreviewViewSize(PREVIEW_IMAGE_WIDTH, PREVIEW_IMAGE_HEIGHT);
        colorCameraPreviewCallback = new ColorCameraPreviewCallback();
        //将摄像头工具类加入到太川摄像头管理类中进行管理
        TcCameraManager.get().setCurrentCameraUtil(TAG, cameraUtils);
    }

    @OnClick({R.id.activity_test_camera_start_preview_button,R.id.activity_test_camera_take_photo_button,
            R.id.activity_test_camera_stop_preview_button,R.id.activity_test_camera_control_fill_light_button,
            R.id.activity_test_camera_control_infrard_light_button,R.id.activity_test_camera_browse_photo_button})
    @Override
    protected void onXmlClick(View v) {
        super.onXmlClick(v);
        switch (v.getId()) {
            case R.id.activity_test_camera_start_preview_button: {       //开始预览
                startPreview();
                break;
            }
            case R.id.activity_test_camera_stop_preview_button: {       //关闭预览
                //停止预览并注销摄像头
                stopPreviewAndDestoryCamera();
                resetState();
                break;
            }
            case R.id.activity_test_camera_control_fill_light_button:{  //补光灯
                if (controlFillLightBtn.getTag().equals("close")) {
                    //开启补光灯
                    if (SystemUtils.isVankeSiteBoxDevice()){
                        if (cameraType == CAMERA_TYPE_TAKE_PHOTO){
                            cameraUtils.controlTakePhotoCameraFillLightInPreview(true);
                        }else {
                            LightControlUtils.getInstance().controlFillLight(true, false);
                        }
                    }else {
                        LightControlUtils.getInstance().controlFillLight(true, false);
                    }
                    controlFillLightBtn.setTag("open");
                    controlFillLightBtn.setText(getStrById(R.string.btn_camera_test_close_fill_light));
                } else {
                    //开启补光灯
                    if (SystemUtils.isVankeSiteBoxDevice()){
                        if (cameraType == CAMERA_TYPE_TAKE_PHOTO){
                            cameraUtils.controlTakePhotoCameraFillLightInPreview(false);
                        }else {
                            LightControlUtils.getInstance().controlFillLight(false, false);
                        }
                    }else {
                        LightControlUtils.getInstance().controlFillLight(false, false);
                    }
                    controlFillLightBtn.setTag("close");
                    controlFillLightBtn.setText(getStrById(R.string.btn_camera_test_open_fill_light));
                }
                break;
            }
            case R.id.activity_test_camera_control_infrard_light_button:{   //红外灯
                if (SystemUtils.isRk3399()) {
                    if (controlInfrardLightBtn.getTag().equals("close")) {
                        //开启红外灯
                        if (SystemUtils.getTcDeviceType() == TcDeviceType.RK3399_VERTICAL_TOUCH_O8A_DOOR){
                            cameraUtils.controlInfrardCameraInfrardLightInPreview(true);
                        }else {
                            LightControlUtils.getInstance().openOrCloseInfraredLight(true);
                        }
                        controlInfrardLightBtn.setTag("open");
                        controlInfrardLightBtn.setText(getStrById(R.string.btn_camera_test_close_infrard_light));
                    } else {
                        //关闭红外灯
                        if (SystemUtils.getTcDeviceType() == TcDeviceType.RK3399_VERTICAL_TOUCH_O8A_DOOR){
                            cameraUtils.controlInfrardCameraInfrardLightInPreview(false);
                        }else {
                            LightControlUtils.getInstance().openOrCloseInfraredLight(false);
                        }
                        controlInfrardLightBtn.setTag("close");
                        controlInfrardLightBtn.setText(getStrById(R.string.btn_camera_test_open_infrard_light));
                    }
                } else {
                    showMsg("当前设备不支持控制红外灯");
                }
                break;
            }
            case R.id.activity_test_camera_take_photo_button:{
                //必须处于预览状态才允许拍照
                if (cameraUtils.getCameraUtilPreviewState() == TcTextureViewCameraUtils.CAMERA_UTIL_PREVIEW_STATE_IN_PREVIEW){
                    cameraUtils.takePhoto(takePhotoCallback);
                }else {
                    showMsg("摄像头当前未处于预览状态，无法执行拍照功能");
                }
                break;
            }
            case R.id.activity_test_camera_browse_photo_button:{
                FileListFragment fileListFragment = new FileListFragment();
                fileListFragment.setArguments(FileListFragment.setBundleValue("拍照结果浏览",PathConfig.getTakePhotoBaseDirPath()));
                getActivityBaseFragmentManager().replace(fileListFragment);
                break;
            }
        }
    }

    /**
     * 相机拍照回调接口
     */
    private final Camera.PictureCallback takePhotoCallback = new Camera.PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            Log.e(TAG, "onPictureTaken: 拍照成功，接收到拍照数据，大小为： " + data.length);
            //将拍照数据存储为照片
            mPresenter.saveTakePhotoImage(cameraUtils.getCameraPreviewWidth(),cameraUtils.getCameraPreviewHeight(),data);

            //恢复预览
            reStartPreview();
        }
    };

    /**
     * 定义一个方法用于开始执行摄像头预览
     */
    private void startPreview() {
        if (SystemUtils.isRk3399()) {
            if (SystemUtils.isVankeSiteBoxDevice()){
                //刷新获取摄像头下标，防止设备因极端情况下（静电，摄像头异常，手动开关USB摄像头操作） 导致摄像头下标混乱
                VankeSiteBoxCameraIdTypeUtils.getInstance().checkVankeSiteBoxCameraIdType();
            }else {         //普通RK3399设备
                //刷新获取摄像头下标，防止设备因极端情况下（静电，摄像头异常，手动开关USB摄像头操作） 导致摄像头下标混乱
                CameraIdTypeUtils.getInstance().checkCheShenCameraIdType();
            }
        }
        //初始化摄像头并开始预览
        initCameraAndPreview(cameraPreviewView.getSurfaceTexture());
        //启动自动抓拍流程，具体是否抓拍由Switch开关控制
        handler.sendEmptyMessageDelayed(START_AUTO_TAKE_PHOTO, AUTO_TAKE_PHOTO_DELAY_TIME);
    }


    /**
     * 定义一个方法用于 停止摄像头预览并重新初始化进行预览
     */
    private void reStartPreview() {
        showLoading();

        //停止预览并注销摄像头
        stopPreviewAndDestoryCamera();
        resetState();

        Observable.just("")
                .observeOn(Schedulers.io())
                .map(new Function<String, Boolean>() {

                    @Override
                    public Boolean apply(String s) throws Exception {
                        //休眠1秒
                        Thread.sleep(1000);
                        //重新打开摄像头画面预览
                        startPreview();
                        return true;
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Boolean>() {
                    @Override
                    public void accept(Boolean aBoolean) throws Exception {
                        hideLoading();
                    }
                });
    }

    /**
     * 定义一个方法用于重置USB摄像头，使其断电 -> 上电
     */
    private void resetUsbCamera() {
        if (!isInResetUsbCamera) {
            //设置进入重置状态
            isInResetUsbCamera = true;
            showLoading();

            //停止预览并注销摄像头
            stopPreviewAndDestoryCamera();

            Observable.just("")
                    .observeOn(Schedulers.io())
                    .map(new Function<String, Boolean>() {
                        @Override
                        public Boolean apply(String s) throws Exception {
                            Logger.t(TAG).e("开始关闭USB摄像头----");
                            //关闭USB摄像头
//                            LightControlUtils.openOrCloseUsbCamera(false);
                            //延时0.5秒
                            Thread.sleep(500);
                            Logger.t(TAG).e("开始打开USB摄像头----");
                            //开启摄像头
//                            LightControlUtils.openOrCloseUsbCamera(true);
                            //再延时1秒，才允许进行操作
                            Thread.sleep(2500);
                            Logger.t(TAG).e("允许操作USB摄像头----");
                            return true;
                        }
                    }).observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Consumer<Boolean>() {
                        @Override
                        public void accept(Boolean aBoolean) {
                            //重置完毕，设置退出重置状态
                            isInResetUsbCamera = false;
                            hideLoading();
                            //刷新获取摄像头下标，防止设备因极端情况下（静电，摄像头异常，手动开关USB摄像头操作） 导致摄像头下标混乱
                            startPreview();
                        }
                    });
        } else {
            Logger.t(TAG).e("USB摄像头已经入重置流程，不重复执行-----");
        }
    }

    /**
     * 定义一个方法用于初始化摄像头，并开启预览
     */
    @SuppressLint("CheckResult")
    private void initCameraAndPreview(final SurfaceTexture surface) {
        Observable.just("")
                .observeOn(Schedulers.io())
                .map(new Function<String, Integer>() {
                    @Override
                    public Integer apply(String s) {
                        //初始化摄像头
                        cameraInitStartTime = System.currentTimeMillis();
                        Log.e(TAG, "apply: ----------开始执行 摄像头初始化流程,当前毫秒数：  " + cameraInitStartTime);
                        int initResult = -222;
                        if (SystemUtils.isVankeSiteBoxDevice()){
                            initResult = cameraUtils.initCamera(false);
                        }else {
                            initResult = cameraUtils.initCamera();
                        }
                        cameraInitTime = System.currentTimeMillis() - cameraInitStartTime;
                        Log.e(TAG, "apply: ----------完成 摄像头初始化流程。【【【总共耗时：  " + cameraInitTime);
                        return initResult;
                    }
                }).observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Integer>() {
                    @Override
                    public void accept(Integer initResult) {
                        try {
                            Log.e(TAG, "accept: " + cameraType + " 摄像头初始化结果：  " + initResult);
                            //如果摄像头初始化成功或者已经初始化过了，就执行预览流程
                            if (initResult == TcTextureViewCameraUtils.CAMERA_OPERATE_RESULT_INIT_SUCESS ||
                                    initResult == TcTextureViewCameraUtils.CAMERA_OPERATE_RESULT_INITED) {
                                //初始化摄像头成功，将标志位置为false
                                isFristDataCallback = true;

                                cameraUtils.setSurfaceTexture(surface);
                                //绑定摄像头
                                cameraUtils.attachCameraForSurfaceTexture();
                                //设置视频画面 左右镜像翻转
                                if (SystemUtils.isNeedOpenCameraMirrorFlipPreview()){
                                    Matrix transform = new Matrix();
                                    transform.setScale(-1, 1, cameraPreviewView.getWidth() / 2, 0);
                                    cameraPreviewView.setTransform(transform);
                                }
                                if (isNeedDataCallback) {
                                    //添加视频帧数据监听
                                    cameraUtils.setPreviewCallbackWithBuffer(colorCameraPreviewCallback);
                                }
                                //开始预览
                                cameraUtils.startCameraPreview();
                            } else {
                                if (initResult == TcTextureViewCameraUtils.CAMERA_OPERATE_RESULT_FAILURE_RETRY_CAMERAID_INFO_CONSISTENT_TIMEOUT) {
                                    Log.e(TAG, "initColorCameraAndPreview: " + cameraType + " 摄像头初始化异常，cameraId类型与传入的 不一致，" +
                                            "并且重新执行初始化流程已达到上线");
                                } else {
                                    Log.e(TAG, "initColorCameraAndPreview: " + cameraType + " 摄像头初始化遭遇系统Expection异常或传入的cameraId下标大于设备摄像头数量");
                                }
                            }
                        } catch (Exception e) {
                            Log.e(TAG, "initColorCameraAndPreview: " + cameraType + " 摄像头 初始化流程执行过程中 遭遇Expection异常:  " + e.getMessage());
                            showMsg(cameraType + " 摄像头 初始化流程执行过程中 遭遇Expection异常，执行USB摄像头复位操作");
                            //TODO 2019.12.4 注释待实现 重置USB摄像头
//                            resetUsbCamera();
                        }
                    }
                });
    }

    /**
     * 定义一个方法用于停止相机预览并注销摄像头
     */
    private void stopPreviewAndDestoryCamera() {
        //取消定时任务
        handler.removeMessages(MSG_CAMERA_ERROR);
        //停止自动抓拍流程
        handler.sendEmptyMessage(STOP_AUTO_TAKE_PHOTO);

        //停止预览
        if (cameraUtils != null) {
            cameraUtils.stopCameraPreview();
            cameraUtils.destoryCamera();
            //重置数据回调缓冲区数组，以准备好初始化不同分辨率下的数组缓冲区大小
            cameraUtils.resetCallbackBuffer();
            isFristDataCallback = true;
        }

        //关闭红外补光灯
        LightControlUtils.getInstance().openOrCloseInfraredLight(false);
        //关闭补光灯
        LightControlUtils.getInstance().controlFillLight(false, false);

        isFristDataCallback = true;

        controlFillLightBtn.setTag("close");
        controlFillLightBtn.setText(getStrById(R.string.btn_camera_test_open_fill_light));
    }

    /**
     * 定义一个方法用于重置摄像头停止预览时需要重置的参数信息，状态变量
     */
    private void resetState() {
        //移除Handler事件
        handler.removeMessages(REFRESH_CAMERA_PARMA_INFO);
        handler.removeMessages(REFRESH_CAMERA_CALLBACK_DATA_INFO);

        //重置参数信息
        cameraInitStartTime = 0;
        cameraInitTime = 0;
        cameraGetDataTime = 0;
        cameraInitTotalTime = 0;
        isFristDataCallback = true;

        //重置控件状态
        cameraInitInfoTv.setText("");
        cameraParmaTv.setText("");
        delayTimeTv.setText("");
    }

    @Override
    public void refreshTakePhotoView(Bitmap cameraBitmap) {
        handler.sendMessage(handler.obtainMessage(REFRESH_TAKE_PHOTO_IMAGE, cameraBitmap));
    }

    private class ColorCameraPreviewCallback implements Camera.PreviewCallback {

        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
//            Log.i(TAG, "onPreviewFrame: 获取到视频帧数据： " + data.length);
            //发布彩色摄像头异常定时事件
            postCameraErrorEvent();
            //将获取到的视频帧数据传入给摄像头工具类
            cameraUtils.setPreviewVideoData(data);
            if (isFristDataCallback) {
                //计算摄像头 【初始化结束】后 到 接收到第一帧数据回调 的执行时间
                cameraGetDataTime = System.currentTimeMillis() - cameraInitStartTime - cameraInitTime;
                //计算摄像头初始化耗时 总时间
                cameraInitTotalTime = cameraInitTime + cameraGetDataTime;
                //初始化成功，通知刷新摄像机初始化信息
                handler.sendEmptyMessage(REFRESH_CAMERA_INIT_INFO);
                //通知刷新数据回调长度
                handler.sendMessage(handler.obtainMessage(REFRESH_CAMERA_CALLBACK_DATA_INFO, data.length));
                //将标志位重置回false
                isFristDataCallback = false;
            } else {
                //获取本帧视频数据的获取时间
                long currentDataTime = System.currentTimeMillis();
                //计算得出两帧之间的间隔时间
                long delayTime = currentDataTime - lastCameraPreviewDataTime;
                handler.sendMessage(handler.obtainMessage(REFRESH_CAMERA_PARMA_INFO, delayTime));
                //刷新视频帧数据获取时间
                lastCameraPreviewDataTime = currentDataTime;
            }
            cameraUtils.addCallbackBuffer();
        }
    }

    /**
     * 定义一个方法用于发布摄像头错误超时事件
     */
    private void postCameraErrorEvent() {
        //发布前先取消上次的超时事件
        handler.removeMessages(MSG_CAMERA_ERROR);
        handler.sendEmptyMessageDelayed(MSG_CAMERA_ERROR, CAMERA_ERROR_TIMEOUT_TIME);
//        Log.i(TAG, "postColorCameraErrorEvent: 发布 摄像头错误超时事件----");
    }

    private Handler handler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            switch (msg.what) {
                case REFRESH_CAMERA_INIT_INFO: {
                    cameraInitInfoTv.setText(String.format("摄像头初始化耗时: %d ms " +
                            "\n获取到视频数据耗时: %d ms" +
                            "\n总耗时: %d ms", cameraInitTime, cameraGetDataTime, cameraInitTotalTime));
                    break;
                }
                case REFRESH_CAMERA_PARMA_INFO: {
                    long delayTime = (long) msg.obj;
                    float frameRate = (float) 1000 / (float) delayTime;
                    delayTimeTv.setText("两帧数据间隔时间：" + delayTime + " ms" + "\n" +
                            String.format("%.2f", frameRate) + " 帧/秒");
                    break;
                }
                case REFRESH_CAMERA_CALLBACK_DATA_INFO: {
                    int dataLength = (int) msg.obj;
                    Camera.Size previewSize = cameraUtils.getPreviewSize();
                    cameraParmaTv.setText("相机数据回调长度： " + dataLength + "\n" +
                            "预览分辨率： " + previewSize.width + " * " + previewSize.height);
                    break;
                }
                case MSG_CAMERA_ERROR: {
                    showMsg("摄像头出现异常，获取不到视频帧数据！");
                    break;
                }
                case START_AUTO_TAKE_PHOTO: {
//                    if (isAutoTakePhoto) {      //启动自动抓拍时开启预览，通过 开始预览按钮开启摄像头 不进入该逻辑
//                        //开启预览
//                        startPreview();
//                    }
                    //执行抓拍
                    if (isAutoTakePhoto && isNeedDataCallback) {
                        if (cameraUtils.getCameraUtilPreviewState() == TcTextureViewCameraUtils.CAMERA_UTIL_PREVIEW_STATE_IN_PREVIEW) {
                            mPresenter.getTcCameraUtilsPreviewFrame();
                        }

//                        if (take_photo_number++<5){     //连续抓拍5次，间隔1秒
//                            Log.i(TAG, "handleMessage: 进入连续抓拍逻辑");
//                            if (!handler.hasMessages(START_AUTO_TAKE_PHOTO)) {
//                                handler.sendEmptyMessageDelayed(START_AUTO_TAKE_PHOTO, CONTINUOUS_TAKE_PHOTO_DELAY_TIME);
//                            }
//                        }else {                         //完成5次抓拍，关闭摄像头，复位相关按钮
//                            take_photo_number = 0;
//                            autoTakephotoSwitch.setChecked(false);
//                            stopPreviewAndDestoryCamera();
//                            resetState();
//                        }

                    }

//                    //延时5秒后再次发送抓拍事件
//                    if (!handler.hasMessages(START_AUTO_TAKE_PHOTO)) {
                    if (!handler.hasMessages(START_AUTO_TAKE_PHOTO)) {
                        handler.sendEmptyMessageDelayed(START_AUTO_TAKE_PHOTO, AUTO_TAKE_PHOTO_DELAY_TIME);
                    }
//                    }
                    break;
                }
                case STOP_AUTO_TAKE_PHOTO: {
                    //移除所有抓拍事件
                    handler.removeMessages(START_AUTO_TAKE_PHOTO);
                    //将抓拍显示控件重置
                    takephotoIv.setImageBitmap(null);
                    break;
                }
                case REFRESH_TAKE_PHOTO_IMAGE: {
                    Bitmap cameraBitmap = (Bitmap) msg.obj;
                    if (cameraBitmap != null) {
                        takephotoIv.setImageBitmap(cameraBitmap);
                    }
                    break;
                }
            }
            return false;
        }
    });

    /**
     * 定义一个内部类用于进行TextureView的状态监听
     */
    private class CameraTextureListener implements TextureView.SurfaceTextureListener {

        @Override
        public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {

        }

        @Override
        public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {

        }

        @Override
        public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
            //停止预览并注销摄像头
            stopPreviewAndDestoryCamera();
            //将摄像头工具类从太川摄像头管理类中移除
            TcCameraManager.get().setCurrentCameraUtil(null, null);
            return false;
        }

        @Override
        public void onSurfaceTextureUpdated(SurfaceTexture surface) {

        }
    }

    @Override
    protected TestCameraPresenter createPresenter() {
        return new TestCameraPresenter(mActivity);
    }

    @Override
    protected boolean isAllowAutoFinishFragment() {
        return false;
    }

    @Override
    public void doOnAutoFinishFragment() {
        mViewFocus.nextFocus();     //TODO 特殊处理，因为大体框架已经下好  所有功能页面统一按 * 号键返回主页面， 此时与自定义控件KSSpinner 内部的 * 号键- - -选择子项 功能冲突，
        // TODO 为避免再退出时再次切换分辨率，在从Activity层下发到Fragment层前，将KSSpinner控件的焦点移除
        resultDialog.show();
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        switch (event.getKeyCode()) {
            case KeyEvent.KEYCODE_1:
                startPreviewButton.performClick();
                break;
            case KeyEvent.KEYCODE_2:
                stopPreviewButton.performClick();
                break;
            case KeyEvent.KEYCODE_3:
                dataCallbackCb.setChecked(!dataCallbackCb.isChecked());
                break;
            case KeyEvent.KEYCODE_4:
                previewSizeTypeSp.mKeyListener.onKey(previewSizeTypeSp, Key.Convert.KEYCODE_XING, event);       //按4键 切换分辨率
                break;
            case KeyEvent.KEYCODE_5:
                autoTakephotoSwitch.setChecked(!autoTakephotoSwitch.isChecked());
                break;
            case KeyEvent.KEYCODE_6:
                controlFillLightBtn.performClick();
                break;
            case KeyEvent.KEYCODE_7:
                if (SystemUtils.isRk3399()){
                    if (cameraType == CAMERA_TYPE_INFRARED) {
                        controlInfrardLightBtn.performClick();
                    }
                }
                break;
            case KeyEvent.KEYCODE_8:
                takePhotoBtn.performClick();
                break;
            case KeyEvent.KEYCODE_9:
                browsePhotoBtn.performClick();
                break;
            case Key.Convert.KEYCODE_JING:
                mViewFocus.handleClick();               //按 * 号键 弹出以及收回 - - - 分辨率下拉框
                break;
        }
        if (resultDialog.isShowing()) {
            resultDialog.dispatchKeyEvent(event);
        }
        return super.dispatchKeyEvent(event);
    }

    @Override
    public int getCameraType() {
        return cameraType;
    }

    @Override
    public String getCameraTypeName() {
        if (cameraType == CAMERA_TYPE_COLOR){
            return "彩色摄像头";
        }else if (cameraType == CAMERA_TYPE_INFRARED){
            return "红外摄像头";
        }else if (cameraType == CAMERA_TYPE_TAKE_PHOTO){
            return "拍单摄像头";
        }else {
            return "未知摄像头";
        }
    }
}
